package com.sailor.aspect;

import com.sailor.annotation.Sailor;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

/**
 * @Description: 用户操作节流切面
 * @create: 2021-06-13 14:39:04
 * @author:wwz
 */
@Aspect
@Component
public class SailorAspect {

    @Autowired
    RedissonClient redissonClient;

    @Pointcut("@annotation(com.sailor.annotation.Sailor)")
    public void pointcut() {
    }

    /**
     * 环绕
     *
     * @param pjp
     * @param sailor
     * @return
     * @throws Throwable
     */
    @Around("pointcut()&&@annotation(sailor)")
    public Object doAround(ProceedingJoinPoint pjp, Sailor sailor) throws Throwable {
        // 节流粒度标记前缀
        String throttleGranularityPrefix = "throttle:operator:"+pjp.getSignature().toLongString();
        // 获取锁还没有进行加锁返回一个RLock
        RLock lock = redissonClient.getLock(throttleGranularityPrefix + "1");
        if (lock.isLocked()) {
            throw new RuntimeException(sailor.msg());
        } else {
            // 进行加锁，本质上还是执行redis的setnx命令，默认30S过期时间
            lock.lock(sailor.timeGap(), TimeUnit.MILLISECONDS);
            // tryLock 传递的时间参数是等待拿锁的时间，不是给锁的过期时间
            //boolean b = lock.tryLock(sailor.timeGap(), TimeUnit.MILLISECONDS);
            return pjp.proceed();
        }
    }
}
